# 通知消息系统数据模型
from django.db import models
from django.contrib.auth.models import User
from django.template import Template, Context
from django.utils import timezone
import json


class NotificationTemplate(models.Model):
    """通知模板模型"""
    NOTIFICATION_TYPE_CHOICES = [
        ('info', '信息'),
        ('success', '成功'),
        ('warning', '警告'),
        ('error', '错误'),
        ('system', '系统'),
    ]
    
    name = models.CharField(max_length=200, unique=True, verbose_name="模板名称")
    description = models.TextField(blank=True, verbose_name="模板描述")
    
    # 模板内容
    title_template = models.CharField(max_length=500, verbose_name="标题模板")
    message_template = models.TextField(verbose_name="消息模板")
    
    # 通知设置
    notification_type = models.CharField(
        max_length=20, 
        choices=NOTIFICATION_TYPE_CHOICES, 
        default='info', 
        verbose_name="通知类型"
    )
    default_channels = models.JSONField(default=list, verbose_name="默认渠道")
    
    # 邮件模板设置
    email_template = models.TextField(blank=True, verbose_name="邮件模板")
    email_subject_template = models.CharField(max_length=500, blank=True, verbose_name="邮件主题模板")
    
    # 短信模板设置
    sms_template = models.TextField(blank=True, verbose_name="短信模板")
    
    # 状态
    is_active = models.BooleanField(default=True, verbose_name="是否启用")
    
    # 使用统计
    use_count = models.PositiveIntegerField(default=0, verbose_name="使用次数")
    last_used_at = models.DateTimeField(null=True, blank=True, verbose_name="最后使用时间")
    
    # 时间信息
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name="创建人")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    
    class Meta:
        verbose_name = "通知模板"
        verbose_name_plural = "通知模板"
        ordering = ['name']
    
    def __str__(self):
        return self.name
    
    def render_title(self, context_data):
        """渲染标题模板"""
        try:
            template = Template(self.title_template)
            context = Context(context_data)
            return template.render(context)
        except Exception as e:
            return f"模板渲染错误: {e}"
    
    def render_message(self, context_data):
        """渲染消息模板"""
        try:
            template = Template(self.message_template)
            context = Context(context_data)
            return template.render(context)
        except Exception as e:
            return f"模板渲染错误: {e}"
    
    def render_email_subject(self, context_data):
        """渲染邮件主题模板"""
        if not self.email_subject_template:
            return self.render_title(context_data)
        
        try:
            template = Template(self.email_subject_template)
            context = Context(context_data)
            return template.render(context)
        except Exception as e:
            return f"邮件主题模板渲染错误: {e}"
    
    def render_email_content(self, context_data):
        """渲染邮件内容模板"""
        if not self.email_template:
            return self.render_message(context_data)
        
        try:
            template = Template(self.email_template)
            context = Context(context_data)
            return template.render(context)
        except Exception as e:
            return f"邮件内容模板渲染错误: {e}"
    
    def render_sms_content(self, context_data):
        """渲染短信内容模板"""
        if not self.sms_template:
            return self.render_message(context_data)
        
        try:
            template = Template(self.sms_template)
            context = Context(context_data)
            return template.render(context)
        except Exception as e:
            return f"短信模板渲染错误: {e}"
    
    def increment_use_count(self):
        """增加使用次数"""
        self.use_count += 1
        self.last_used_at = timezone.now()
        self.save(update_fields=['use_count', 'last_used_at'])


class NotificationRule(models.Model):
    """通知规则模型"""
    TRIGGER_TYPE_CHOICES = [
        ('asset_created', '资产创建'),
        ('asset_updated', '资产更新'),
        ('asset_deleted', '资产删除'),
        ('maintenance_due', '维修到期'),
        ('maintenance_completed', '维修完成'),
        ('inventory_low', '库存不足'),
        ('borrow_overdue', '借用逾期'),
        ('contract_expiring', '合同到期'),
        ('system_alert', '系统告警'),
        ('custom', '自定义'),
    ]
    
    name = models.CharField(max_length=200, verbose_name="规则名称")
    description = models.TextField(blank=True, verbose_name="规则描述")
    
    # 触发条件
    trigger_type = models.CharField(max_length=50, choices=TRIGGER_TYPE_CHOICES, verbose_name="触发类型")
    trigger_conditions = models.JSONField(default=dict, verbose_name="触发条件")
    
    # 通知设置
    template = models.ForeignKey(NotificationTemplate, on_delete=models.CASCADE, verbose_name="通知模板")
    channels = models.JSONField(default=list, verbose_name="通知渠道")
    
    # 接收人设置
    notify_users = models.ManyToManyField(User, blank=True, verbose_name="通知用户")
    notify_groups = models.ManyToManyField('auth.Group', blank=True, verbose_name="通知用户组")
    notify_roles = models.JSONField(default=list, verbose_name="通知角色")  # 如：管理员、部门负责人等
    
    # 频率控制
    frequency_limit = models.PositiveIntegerField(default=0, verbose_name="频率限制(分钟)")  # 0表示无限制
    last_triggered_at = models.DateTimeField(null=True, blank=True, verbose_name="最后触发时间")
    
    # 状态
    is_active = models.BooleanField(default=True, verbose_name="是否启用")
    
    # 统计信息
    trigger_count = models.PositiveIntegerField(default=0, verbose_name="触发次数")
    success_count = models.PositiveIntegerField(default=0, verbose_name="成功次数")
    
    # 时间信息
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name="创建人")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    
    class Meta:
        verbose_name = "通知规则"
        verbose_name_plural = "通知规则"
        ordering = ['-created_at']
    
    def __str__(self):
        return self.name
    
    def can_trigger(self):
        """检查是否可以触发"""
        if not self.is_active:
            return False
        
        if self.frequency_limit > 0 and self.last_triggered_at:
            time_diff = timezone.now() - self.last_triggered_at
            if time_diff.total_seconds() < self.frequency_limit * 60:
                return False
        
        return True
    
    def trigger_notification(self, context_data=None):
        """触发通知"""
        if not self.can_trigger():
            return {
                'success': False,
                'error': '通知规则暂时无法触发'
            }
        
        try:
            from .notification_service import notification_service
            
            # 获取接收人
            recipients = self.get_recipients(context_data)
            
            if not recipients:
                return {
                    'success': False,
                    'error': '没有找到通知接收人'
                }
            
            # 渲染通知内容
            title = self.template.render_title(context_data or {})
            message = self.template.render_message(context_data or {})
            
            # 发送通知
            result = notification_service.send_notification(
                users=recipients,
                title=title,
                message=message,
                notification_type=self.template.notification_type,
                channels=self.channels
            )
            
            # 更新统计信息
            self.trigger_count += 1
            self.last_triggered_at = timezone.now()
            
            # 统计成功数量
            success_count = 0
            for channel_results in result.values():
                for channel_result in channel_results:
                    if channel_result.get('success'):
                        success_count += 1
            
            if success_count > 0:
                self.success_count += success_count
            
            self.save(update_fields=['trigger_count', 'last_triggered_at', 'success_count'])
            
            return {
                'success': True,
                'result': result,
                'recipients_count': len(recipients)
            }
            
        except Exception as e:
            return {
                'success': False,
                'error': str(e)
            }
    
    def get_recipients(self, context_data=None):
        """获取通知接收人"""
        recipients = set()
        
        # 添加指定用户
        recipients.update(self.notify_users.all())
        
        # 添加用户组成员
        for group in self.notify_groups.all():
            recipients.update(group.user_set.all())
        
        # 添加角色用户
        for role in self.notify_roles:
            role_users = self._get_users_by_role(role, context_data)
            recipients.update(role_users)
        
        return list(recipients)
    
    def _get_users_by_role(self, role, context_data=None):
        """根据角色获取用户"""
        users = []
        
        if role == 'admin':
            users = User.objects.filter(is_superuser=True)
        elif role == 'staff':
            users = User.objects.filter(is_staff=True)
        elif role == 'department_manager' and context_data:
            # 获取部门负责人
            department = context_data.get('department')
            if department and hasattr(department, 'manager'):
                users = [department.manager]
        elif role == 'asset_owner' and context_data:
            # 获取资产负责人
            asset = context_data.get('asset')
            if asset and hasattr(asset, 'owner'):
                users = [asset.owner]
        
        return users


class NotificationLog(models.Model):
    """通知日志模型"""
    CHANNEL_CHOICES = [
        ('system', '系统通知'),
        ('email', '邮件'),
        ('sms', '短信'),
        ('push', '推送'),
    ]
    
    STATUS_CHOICES = [
        ('pending', '待发送'),
        ('sent', '已发送'),
        ('failed', '发送失败'),
        ('delivered', '已送达'),
        ('read', '已读'),
    ]
    
    # 通知信息
    user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="接收用户")
    title = models.CharField(max_length=500, verbose_name="通知标题")
    message = models.TextField(verbose_name="通知内容")
    
    # 发送信息
    channel = models.CharField(max_length=20, choices=CHANNEL_CHOICES, verbose_name="发送渠道")
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending', verbose_name="发送状态")
    
    # 关联信息
    rule = models.ForeignKey(NotificationRule, on_delete=models.SET_NULL, null=True, blank=True, verbose_name="关联规则")
    template = models.ForeignKey(NotificationTemplate, on_delete=models.SET_NULL, null=True, blank=True, verbose_name="使用模板")
    
    # 发送详情
    recipient_address = models.CharField(max_length=200, blank=True, verbose_name="接收地址")  # 邮箱、手机号等
    external_id = models.CharField(max_length=200, blank=True, verbose_name="外部ID")  # 第三方服务返回的ID
    error_message = models.TextField(blank=True, verbose_name="错误信息")
    
    # 时间信息
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    sent_at = models.DateTimeField(null=True, blank=True, verbose_name="发送时间")
    delivered_at = models.DateTimeField(null=True, blank=True, verbose_name="送达时间")
    read_at = models.DateTimeField(null=True, blank=True, verbose_name="阅读时间")
    
    class Meta:
        verbose_name = "通知日志"
        verbose_name_plural = "通知日志"
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['user', 'status', '-created_at']),
            models.Index(fields=['channel', 'status']),
        ]
    
    def __str__(self):
        return f"{self.user.username} - {self.title} - {self.get_channel_display()}"
    
    def mark_as_sent(self, external_id=None):
        """标记为已发送"""
        self.status = 'sent'
        self.sent_at = timezone.now()
        if external_id:
            self.external_id = external_id
        self.save(update_fields=['status', 'sent_at', 'external_id'])
    
    def mark_as_failed(self, error_message):
        """标记为发送失败"""
        self.status = 'failed'
        self.error_message = error_message
        self.save(update_fields=['status', 'error_message'])
    
    def mark_as_delivered(self):
        """标记为已送达"""
        self.status = 'delivered'
        self.delivered_at = timezone.now()
        self.save(update_fields=['status', 'delivered_at'])
    
    def mark_as_read(self):
        """标记为已读"""
        self.status = 'read'
        self.read_at = timezone.now()
        self.save(update_fields=['status', 'read_at'])


class NotificationPreference(models.Model):
    """用户通知偏好模型"""
    user = models.OneToOneField(User, on_delete=models.CASCADE, verbose_name="用户")
    
    # 渠道偏好
    enable_system_notifications = models.BooleanField(default=True, verbose_name="启用系统通知")
    enable_email_notifications = models.BooleanField(default=True, verbose_name="启用邮件通知")
    enable_sms_notifications = models.BooleanField(default=False, verbose_name="启用短信通知")
    enable_push_notifications = models.BooleanField(default=True, verbose_name="启用推送通知")
    
    # 通知类型偏好
    notification_types = models.JSONField(default=dict, verbose_name="通知类型偏好")
    
    # 时间偏好
    quiet_hours_start = models.TimeField(null=True, blank=True, verbose_name="免打扰开始时间")
    quiet_hours_end = models.TimeField(null=True, blank=True, verbose_name="免打扰结束时间")
    
    # 频率控制
    email_frequency = models.CharField(
        max_length=20,
        choices=[
            ('immediate', '立即'),
            ('hourly', '每小时'),
            ('daily', '每日'),
            ('weekly', '每周'),
        ],
        default='immediate',
        verbose_name="邮件频率"
    )
    
    # 联系信息
    phone = models.CharField(max_length=20, blank=True, verbose_name="手机号")
    push_token = models.CharField(max_length=500, blank=True, verbose_name="推送Token")
    
    # 时间信息
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    
    class Meta:
        verbose_name = "通知偏好"
        verbose_name_plural = "通知偏好"
    
    def __str__(self):
        return f"{self.user.username} - 通知偏好"
    
    def is_channel_enabled(self, channel):
        """检查渠道是否启用"""
        channel_map = {
            'system': self.enable_system_notifications,
            'email': self.enable_email_notifications,
            'sms': self.enable_sms_notifications,
            'push': self.enable_push_notifications,
        }
        return channel_map.get(channel, False)
    
    def is_in_quiet_hours(self):
        """检查是否在免打扰时间内"""
        if not self.quiet_hours_start or not self.quiet_hours_end:
            return False
        
        now = timezone.now().time()
        
        if self.quiet_hours_start <= self.quiet_hours_end:
            # 同一天内的时间段
            return self.quiet_hours_start <= now <= self.quiet_hours_end
        else:
            # 跨天的时间段
            return now >= self.quiet_hours_start or now <= self.quiet_hours_end